﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Noris.Schedule.Support;
using Noris.Schedule.Support.Core;

namespace Noris.Schedule.UI.Forms
{
	public partial class NonInteractiveForm : Form, ICallBackTarget
	{
		#region INICIACE FORMULÁŘE
		public NonInteractiveForm()
		{
			InitializeComponent();
			this._Init();
		}
		private _CowleyStatus _CwlStatus;
		private bool _FormVisible;
		private bool _BaloonVisible;
		private decimal _ProgressRatio;
		private bool _FormCloseEnabled;
		private Size _NormalSize;
		private void NonInteractiveForm_Load(object sender, EventArgs e)
		{
		}

		private void _Init()
		{
			this._CwlStatus = _CowleyStatus.None;
			this._ProgressBar.Minimum = 0;
			this._ProgressBar.Maximum = 1000;
			this._FormCloseEnabled = false;
			this._NormalSize = this.Size;
			this.FormClosing += new FormClosingEventHandler(NonInteractiveForm_FormClosing);
			this.Shown += new EventHandler(NonInteractiveForm_Shown);
			this.ClientSizeChanged += new EventHandler(NonInteractiveForm_ClientSizeChanged);
			this._NotifyIcon.MouseDoubleClick += new MouseEventHandler(_NotifyIcon_MouseDoubleClick);
			this._NotifyIcon.MouseClick += new MouseEventHandler(_NotifyIcon_MouseClick);
			this._NotifyIcon.BalloonTipClicked += new EventHandler(_NotifyIcon_BalloonTipClicked);
			this._NotifyIcon.BalloonTipClosed += new EventHandler(_NotifyIcon_BalloonTipClosed);
			this._PgText.ForeColor = this.ForeColor;
		}
		#endregion
		#region OBSLUHA UDÁLOSTÍ FORMU
		void NonInteractiveForm_Shown(object sender, EventArgs e)
		{
			if (this._CwlStatus == _CowleyStatus.None)
			{
				try
				{
					Cowley.RunCowley(Steward.CowleyIdFromParams, this as ICallBackTarget);
					this._CwlStatus = _CowleyStatus.Running;
					this._FormVisible = true;
				}
				catch (Exception exc)
				{
					Steward.Audit(AuditRowType.CoreError, exc.Message, exc);
					Dialog.ShowError(exc);
					this._FormCloseEnabled = true;
				}
			}
		}
		void NonInteractiveForm_ClientSizeChanged(object sender, EventArgs e)
		{
			if (this.WindowState == FormWindowState.Normal && this.Height > 100)
				this._NormalSize = this.Size;

			if (this.WindowState == FormWindowState.Minimized && this._FormVisible)
				this._FormHide();
		}
		void NonInteractiveForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (this._FormCloseEnabled) return;           // Zavření je povoleno, provede se.

			// Zavření není povoleno, namísto toho se okno schová:
			this._FormHide();
			// this._ShowTrayIcon();

			e.Cancel = true;
		}
		/// <summary>
		/// Klik na balon: otevření okna
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void _NotifyIcon_BalloonTipClicked(object sender, EventArgs e)
		{
			if (this._FormVisible) return;
			this._FormShow();
		}
		/// <summary>
		/// Klik na ikonu: otevření balonu
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void _NotifyIcon_MouseClick(object sender, MouseEventArgs e)
		{
			this._BaloonVisible = true;
		}
		/// <summary>
		/// Doubleklik na ikonu: otevření okna
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void _NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			if (this._FormVisible) return;
			this._FormShow();
		}
		/// <summary>
		/// Když uživatel klikne na Balon.Close, tak tooltip zavřu a neukážu.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void _NotifyIcon_BalloonTipClosed(object sender, EventArgs e)
		{
			this._NotifyIconShow(1);
			this._BaloonVisible = false;
		}
		/// <summary>
		/// Vytáhne toto okno z tray
		/// </summary>
		void _FormShow()
		{
			this._FormVisible = true;
			this.ShowInTaskbar = true;
			this._BaloonVisible = false;
			this._NotifyIcon.Visible = false;
			if (this.WindowState == FormWindowState.Minimized)
			{
				this.WindowState = FormWindowState.Normal;
			}
			this.Show();
			if (this.Height <= 100 && this._NormalSize.Height > 100)
				this.Size = this._NormalSize;
			this.Focus();
			this.Activate();
		}
		protected override bool ShowWithoutActivation { get { return true; } }
		/// <summary>
		/// Skryje toto okno do Tray, místo toho rozsvítí aktivní balon tip
		/// </summary>
		void _FormHide()
		{
			if (this.WindowState == FormWindowState.Normal && this.Height > 100)
				this._NormalSize = this.Size;

			this._FormVisible = false;
			this._BaloonVisible = true;
			this._NotifyIcon.Visible = true;
			this.ShowInTaskbar = false;
			this.Hide();
			this._NotifyIconRefresh();
		}
		/// <summary>
		/// Zavře toto okno (Close), včetně nastavení povolenky this._FormCloseEnabled = true;
		/// </summary>
		void _FormClose()
		{
			this._FormCloseEnabled = true;
			if (this._BaloonVisible)
				this._NotifyIcon.Visible = false;
			this.Close();
		}
		private enum _CowleyStatus { None, Running, Finished }
		#endregion


		#region ICallBackTarget Members : metoda volaná odkudsi z procesu, invokace zdejších výkonných metod (progres bar, texty, Done)
		void ICallBackTarget.CallTarget(object sender, CallBackTargetArgs args)
		{
			// Progress si sám odchytává a řeší svoje volání (DoProgress, CreateSegment):
			// Tuto operaci je nutno provést ihned, bez invokace do owner threadu, 
			//   protože jejím důsledkem (pro args.ProcessState == CallBackProcessState.CreateSegment) bude vytvoření segmentu a jeho vložení do args.ProgrSegment,
			//   kde jej očekává volající metoda v tomto threadu - který skončí okamžitě (pro invokaci se využívá asynchronní proces):
			this._ProgressBar.CallProgress(args);

			// Další už může počkat na invokaci:
			if (this.InvokeRequired)
				this.BeginInvoke(new Action<CallBackTargetArgs>(this._CallTarget), args);
			else
				this._CallTarget(args);
		}
		private void _CallTarget(CallBackTargetArgs args)
		{
			// Požadavky, které realizuje okno:
			switch (args.ProcessState)
			{
				case CallBackProcessState.SetTitle:
					if (args.FormTitle != null)
						this.Text = args.FormTitle;
					if (args.SubTitle != null)
						this._PgLabel.Text = args.SubTitle;
					break;
				case CallBackProcessState.DoProgress:
				case CallBackProcessState.ShowText:
					if (args.ProcessState == CallBackProcessState.DoProgress)
					{
						this._ProgressRatio = args.Ratio;
					}
					if (args.TextLines != null)
						this._PgText.Text = args.TextLines;

					if (!this._FormVisible)
						this._NotifyIconRefresh();

					break;

				case CallBackProcessState.Succeed:
				case CallBackProcessState.Failed:
					this._CwlStatus = _CowleyStatus.Finished;
					this._CallDone();
					break;
			}
		}
		private void _CallDone()
		{
			this._FormClose();
		}
		#endregion
		/// <summary>
		/// U tray ikony rozsvítí balon s aktuálním textem
		/// </summary>
		private void _NotifyIconRefresh()
		{
			if (this._FormVisible) return;

			this._NotifyIconShow(360);
		}
		/// <summary>
		/// Z aktuálních proměnných (this.Text, this._PgLabel.Text, this._ProgressRatio) sestaví informaci a zobrazí ji v baloon tipu.
		/// </summary>
		/// <param name="timeOut"></param>
		private void _NotifyIconShow(int timeOut)
		{
			string title = this.Text + ", " + this._PgLabel.Text;
			decimal percent = Math.Round(100M * this._ProgressRatio, 1);
			string text = percent.ToString() + "%" + Environment.NewLine + this._PgText.Text;

			this._NotifyIcon.Text = text;

			if (this._BaloonVisible)
			{
				if (String.IsNullOrEmpty(title))
					title = "Informace";
				if (String.IsNullOrEmpty(text))
					text = "Postup prací";

				this._NotifyIcon.ShowBalloonTip(timeOut, title, text, ToolTipIcon.Info);
				this._NotifyIcon.BalloonTipText = text;
			}
		}
	}
}
